home *** CD-ROM | disk | FTP | other *** search
/ Pascal Super Library / Pascal Super Library (CW International)(1997).bin / PGM_TOOL / RLINE_OP / RLINE.ASM < prev    next >
Assembly Source File  |  1989-10-06  |  14KB  |  515 lines

  1.     IDEAL
  2.  
  3. SEGMENT data     word     public
  4.     EXTRN    FileMode:BYTE
  5. ENDS
  6.  
  7. SEGMENT    code     byte    public
  8.     ASSUME    cs:code,ds:data
  9.  
  10. ; set up a STRUCture compatible with the Pascal RFobject object.
  11. STRUC    RFrec
  12.     Handle    dw    ?    ; File handle
  13.     BufStart dw    ?    ; Offset Disk buffer
  14.     BufES    dw    ?    ; Segment Disk buffer = es
  15.     BufDI    dw    ?    ; Current buffer position = di
  16.     BSize    dw    ?    ; Buffer size
  17.     BufCX    dw    ?    ; Bytes left to search = cx
  18.     NBufs    dw    ?    ; Number of buffers read.
  19.     TotRead    dw    ?    ; Total bytes last read into buffer.
  20.     RFerror dw    ?    ; Error code.
  21. ENDS
  22.  
  23. RFWordSize    equ    9    ; size of RFrec in words.
  24. @self        equ    bp+6    ; Location of self on stack
  25.  
  26. MACRO    BpSp
  27.     push bp
  28.     mov  bp, sp
  29. ENDM
  30.  
  31. MACRO    SpBp NRet
  32.     mov  sp, bp
  33.     pop  bp
  34.     ifnb <NRet>
  35.     ret  NRet
  36.     else
  37.     ret
  38.     endif
  39. ENDM
  40.  
  41.  
  42. ; FOpen and FClose. ***************************************************
  43.  
  44. PUBLIC    RFobject@FOpen, RFobject@FClose
  45.  
  46.     RFesdi        equ    (RFrec ptr es:di)
  47.  
  48.     ;-----------------------------------------------------------------
  49.     ;  Fill RFrec at es:di with 0's
  50.     ;
  51.     ;Registers
  52.     ;  ax, cx
  53.  
  54.     PROC Fill0 NEAR
  55.         push di
  56.         xor  ax, ax        ; fill RFrec fields with 0.
  57.         mov  cx, RFWordSize    ; CX = #words to fill
  58.         rep  stosw
  59.         pop  di
  60.         ret
  61.     ENDP
  62.  
  63. ;-------------------------------------------------------------------------
  64. ; PROCEDURE FOpen(Fn : Str80;
  65. ;          DBsize : Word;
  66. ;          VAR BufP) : Word;
  67. ;  RFerror = 0 on success, DOS error code on failure.
  68.  
  69.     Fn    equ    bp+16    ; address of filename
  70.     DBsize    equ    bp+14    ; requested size of buffer
  71.     BufP    equ    bp+10    ; Ofs of Buffer
  72.  
  73. PROC RFobject@FOpen FAR
  74.     BpSp
  75.     sub  sp, 81    ; allocate local stack
  76.     mov  dx, sp    ; dx = offset asciiz
  77.     push ds        ; save turbo's DS
  78.  
  79.     mov  bl, [FileMode]    ; save filemode in bl
  80.     and  bl, 11111000b    ; make sure it's read-only
  81.  
  82.     ; copy Fn to stack
  83.         lds  si, [Fn]        ; point to Fn[0]
  84.     cld
  85.     lodsb
  86.     mov  cx, 80
  87.     cmp  al, cl        ; check length
  88.     jae  LenOK
  89.     mov  cl, al
  90. LenOK:    mov  di, dx        ; di = offset of asciiz = dx
  91.     push ss
  92.     pop  es            ; es:di points to local space
  93.     rep  movsb
  94.     mov  [es:di], cl    ; store asciiz 0
  95.     push ss
  96.     pop  ds            ; ds:dx points to asciiz
  97.  
  98.     les  di, [@self]    ; es:di points to RFrec.
  99.     call Fill0        ; fill with 0
  100.     cmp  [DBsize], ax    ; Is requested buffer size > 0
  101.     jnz  BSizeOK        ; Yes.
  102.     mov  ax, 12        ; No. Return invalid file access code.
  103.     jmp  short OpenDone
  104. BSizeOK:
  105.     mov  al, bl        ; FileMode
  106.     mov  ah, 3dh        ; ah=3D, DOS open file function
  107.     int  21h
  108.     jc   OpenDone        ; if DOS error, return with code in AX
  109.  
  110.     mov  [RFesdi.Handle], ax ; else set RFrec.Handle,
  111.     mov  ax, [DBsize]    ;  and buffer size,
  112.     mov  [RFesdi.BSize], ax
  113.     lds  si, [BufP]        ;  and RF Buffer address.
  114.     mov  [RFesdi.BufStart], si
  115.     mov  ax, ds
  116.     mov  [RFesdi.BufES], ax
  117.     xor  ax, ax        ; and return success.
  118. OpenDone:
  119.     mov  [RFesdi.RFerror], ax
  120.     pop  ds            ; restore Turbo DS
  121.     SpBp 14
  122. ENDP
  123.  
  124.  
  125. ;-------------------------------------------------------------------------
  126. ; PROCEDURE FClose;
  127. ;  Closes Handle if BSize > 0 and Handle > 4
  128.  
  129. PROC RFobject@FClose FAR
  130.     BpSp
  131.     les  di, [@self]    ; ES:DI points to RFrec
  132.  
  133.     cmp  [RFesdi.BSize], 0    ; Had it been opened?
  134.     jz   DoneClose        ; No, get out.
  135.     mov  bx, [RFesdi.Handle] ; BX = RF.Handle
  136.     call Fill0
  137.  
  138.     cmp  bx, 4        ; If attempting to close
  139.     jbe  DoneClose        ;  standard DOS device, DON'T.
  140.     mov  ah, 3eh        ; DOS close file function
  141.     int  21h
  142. DoneClose:
  143.     SpBp 4
  144. ENDP
  145.  
  146.  
  147. ; FILLBUF local proc ****************************************************
  148. ;
  149. ; Fill disk buffer. Read RF.BSize bytes from file RF.Handle to ES:[BufStart].
  150. ;            On last buffer, last ^Z is stripped.
  151. ;Input:
  152. ;    DS:BX points to RFrec.
  153. ;    ES = segment of Buffer. ( RF.BufES )
  154. ;    RFrec is at BP+10
  155. ;Output:
  156. ;   If Failed, returns carry flag set, reason in AX:
  157. ;    a) if a DOS error occurs, the DOS Error code is returned in ax.
  158. ;    b) if end of file (0 bytes left to read),  AX is set to $FFFF
  159. ;
  160. ;   If Successful, returns carry flag clear and:
  161. ;    a) di points to buffer start.
  162. ;    b) cx = number of bytes read.
  163. ;
  164. ; Registers:
  165. ;    ax, cx, di, si
  166.  
  167.     RFbx    equ    (RFrec ptr bx)
  168.  
  169. PROC FillBuf NEAR
  170.     mov  si, dx        ; save Line length
  171.     mov  cx, [RFbx.BSize]
  172.     mov  dx, [RFbx.BufStart] ; point DX to buffer offset.
  173.     mov  di, dx        ; (reset BufDI for later)
  174.     mov  bx, [RFbx.Handle]    ; bx = Handle
  175.     mov  ax, es
  176.     mov  ds, ax        ; set DS:dx
  177.     mov  ah, 3fh        ; DOS read file function.
  178.     int  21h
  179.     mov  dx, si        ; restore Line Length
  180.     lds  bx, [@self]        ; restore RFrec address
  181.     jc   GetOut        ; BlockRead error?
  182.  
  183.     mov  cx, ax        ; cx = #bytes read.
  184.     jcxz EOF        ; if no bytes read, we're done
  185.  
  186.     ; some bytes were read
  187.     inc  [RFbx.NBufs]    ; update file position
  188.     ; remove ^Z at eof
  189.     xchg bx, cx        ; save RFrec offset and index BX
  190.     cmp  [byte es:di+bx-1], 26 ; end of buffer a ^Z?
  191.     xchg bx, cx        ; restore RFrec ofs and cx
  192.     jne  NoCtrlZ        ; no, go on.
  193.     dec  cx            ; yes. Dec bytes read
  194. NoCtrlZ:
  195.     mov  [RFbx.TotRead], cx    ; Store number bytes read.
  196.     jcxz EOF        ; if cx = 0 then EOF
  197.     clc            ; Return success.
  198.     ret
  199. EOF:    mov  ax, 0FFFFh        ; set result to EOF
  200.     stc            ; Return failure.
  201. GetOut:    ret
  202. ENDP
  203.  
  204.  
  205. ; RFREADLN and BUFMOVE ***********************************************
  206.  
  207. PUBLIC    RFobject@FReadLn
  208.     RFbx        equ    (RFrec ptr bx)
  209.     RString        equ    bp+10 ; address of Return String
  210.  
  211. ;----------------------------------------------------------------------
  212. ; BufMove -
  213. ;  Appends CX number of bytes from ES:DI to RString.
  214. ;  Will not move more than 255 bytes to RString.  If there are more to move,
  215. ; the rest are thrown away.
  216. ;  Leading ^J's are stripped.
  217. ;
  218. ;  Called only by FReadln.
  219. ;
  220. ;  Input
  221. ;    ES:SI = address of bytes to move from.
  222. ;    CX    = # Bytes to move. If CX = 0, length byte is set.
  223. ;    DX    = current length of RString
  224. ;    RString is at [BP+6]
  225. ;    Direction Flag clear.
  226. ;
  227. ; Registers
  228. ;  ax, cx, es, di, si
  229. ;  DX updated to new length of RString
  230.  
  231. PROC BufMove NEAR
  232.     push ds            ; save RF segment
  233.     jcxz LengthOK        ; Any bytes to move?
  234.     cmp  [byte es:si], 10    ; yes. Got a ^J?
  235.     jne  NoCtrlJ
  236.     dec  cx            ; yes. fix cx and si
  237.     jz   LengthOK        ; Any bytes to move now?
  238.     inc  si
  239. NoCtrlJ:
  240.     mov  ds, [RFbx.BufES]    ; DS:SI = Source address.
  241.     mov  ax, 255        ; ax = max length RString can be.
  242.     sub  ax, dx        ; ax = max length CX can be.
  243.     je   BDone        ; If RString = max length, get out.
  244.  
  245.     cmp  cx, ax        ; are there more than max to move?
  246.     jbe  LengthOK        ; If not, go on.
  247.     mov  cx, ax        ; yes. set cx to ax.
  248. LengthOK:
  249.     les  di, [RString]    ; es:di points to RString[0]
  250.     mov  al, dl        ; AL = Length(RString)
  251.     add  al, cl        ; Add bytes to move.
  252.     stosb            ; Set RString[0].  DI = ofs Rstring[1].
  253.     jcxz BDone        ; anything to move now?
  254.  
  255.     add  di, dx        ; es:di => RString[dl+1]
  256.     mov  dl, al        ; update length
  257.     shr  cx, 1
  258.     rep  movsw        ; Move cx words.
  259.     rcl  cx, 1
  260.     rep  movsb        ; Move odd byte, if any.
  261. BDone:    pop  ds            ; Restore RF segment.
  262.     ret
  263. ENDP
  264.  
  265.  
  266. ;-------------------------------------------------------------------------
  267. ; PROCEDURE FReadLn(VAR RString : String);
  268. ;
  269. ; If successful:
  270. ;    Returns 0.
  271. ;    RString = string read.
  272. ; If failed:
  273. ;    Returns either DOS error code
  274. ;    or $FFFF if EOF.
  275. ;
  276. ; Calls: FillBuf, BufMove.
  277.  
  278. PROC RFobject@FReadLn FAR
  279.     BpSp
  280.     push ds            ; save turbo's DS
  281.     cld            ; forward string operations.
  282.  
  283.     xor  dx, dx        ; dx = string length = 0
  284.     mov  cx, dx        ; cx = 0.
  285.     lds  bx, [@self]        ; ds:bx points to RFrec
  286.     mov  di, [RFbx.BufDI]    ; DI = Buffer offset.
  287.     mov  es, [RFbx.BufES]    ; ES:DI points to buffer.
  288.  
  289.     or   cx, [RFbx.BufCX]    ; CX = number bytes left to scan
  290.     jz   FillIt        ; if 0 then fill the buffer.
  291.  
  292. Scan:    mov  si, di        ; save original buffer position
  293.     push cx            ; save numbytes to scan for
  294.     mov  al, 13        ; scan for CR
  295.     repne scasb
  296.     pop  ax            ; ax = numbytes before scasb
  297.     jz   Found
  298.  
  299.     ; wasn't found. Restore old CX for Bufmove.
  300.     mov  cx, ax        ; restore cx for BufMove.
  301.     call BufMove        ; move results to RString,
  302.     mov  es, [RFbx.BufES]    ; restore Buffer segment,
  303. FillIt:    call near FillBuf    ; refill the buffer
  304.     jnc  Scan        ; If no error, then keep searching.
  305.  
  306.     ; Either EOF or DOS error occurred.
  307.     cmp  ax, 0ffffh        ; EOF?
  308.     jne  Done        ; No, DOS error. Get out.
  309.  
  310.     ; EOF was returned from FillBuf.  If nothing has been
  311.     ;  stored in RString, then we're done, else return no error.
  312.     or   dl, dl        ; Length(RString) = 0?
  313.     jz   Done        ; Yes, return FillBuf's EOF.
  314.     inc  ax            ; report no error.
  315.     mov  [RFbx.BufCX], ax    ; Force FillBuf call next time.
  316.     mov  cx, [RFbx.BufStart] ; make BufDI adjustment to
  317.     add  cx, [RFbx.TotRead]    ;  make FFilePos accurate
  318.     mov  [RFbx.BufDI], cx
  319.     jmp  short done
  320.  
  321. Found:                ; ^M was found.
  322.     mov  [RFbx.BufDI], di    ; Set up RFrec for next time.
  323.     mov  [RFbx.BufCX], cx
  324.     sub  ax, cx        ; Set up to move to RString.
  325.     dec  ax            ; Don't count the ^M.
  326.     mov  cx, ax
  327.     call BufMove
  328.     xor  ax, ax        ; set return code = 0.
  329.  
  330. Done:    mov [RFbx.RFerror], ax
  331.     pop  ds            ; Restore everything and return.
  332.     SpBp 8
  333. ENDP
  334.  
  335.  
  336. ; FREAD ****************************************************************
  337. ;
  338. ; PROCEDURE FRead(VAR Ch : Char);
  339. ; If successful:
  340. ;    Returns 0.
  341. ;    Ch = Character read from file.
  342. ;         All ctrl chars pass, except ^Z at end of file, if there is one.
  343. ; If failed:
  344. ;    Returns either DOS error code
  345. ;    or $FFFF if EOF.
  346. ;
  347. PUBLIC    RFobject@FRead
  348.     RFbx    equ    (RFrec ptr bx)
  349.     RCh    equ    bp+10    ; address of Return Char
  350.  
  351. PROC RFobject@FRead FAR
  352.     BpSp            ; set up pascal stack frame.
  353.     mov  dx, ds        ; save turbo's DS
  354.     cld            ; all forward string operations.
  355.  
  356.     lds  bx, [@self]    ; DS:BX points to RFrec
  357.     xor  cx, cx
  358.     or   cx, [RFbx.BufCX]    ; CX = number of bytes left.
  359.     jz   FillB
  360.     mov  si, [RFbx.BufDI]    ; si = Buffer offset.
  361.     dec  [RFbx.BufCX]    ; Set up RFrec for next time.
  362.     inc  [RFbx.BufDI]
  363.     mov  ds, [RFbx.BufES]    ; ES:si points to buffer.
  364.     les  di, [RCh]        ; set VAR Ch and result.
  365.     movsb
  366.  
  367. SetCh:    xor  ax, ax        ; set return code.
  368. @Done:    mov  [RFbx.RFerror], ax
  369.     mov  ds, dx        ; Restore everything and return.
  370.     SpBp 8
  371.  
  372. FillB:    call near FillBuf    ; Fill the buffer
  373.     jc   @Done        ; If error or EOF, then exit.
  374.     dec  cx            ; the character is in ES:DI
  375.     mov  [RFbx.BufCX], cx    ; Set up RFrec for next time.
  376.     mov  al, [es:di]    ; AL = the character.
  377.     inc  di
  378.     mov  [RFbx.BufDI], di
  379.     les  di, [RCh]        ; set VAR Ch and result.
  380.     stosb
  381.     jmp  short SetCh
  382. ENDP
  383.  
  384. ; FSEEK ***************************************************************
  385. ;
  386. ; PROCEDURE FSeek(FPo : LongInt);
  387. ; Seeks to FPo and fills buffer.
  388. ;
  389. ; If successful:
  390. ;    Returns 0
  391. ;
  392. ; If failed:
  393. ;    Returns DOS error code if DOS error occured.
  394. ;    If BSize = 0, FSeek returns 200 (TP divide by zero error)
  395. ;       This error won't ever occur unless the file hasn't been opened
  396. ;       before calling FSeek.
  397. ;
  398. ; RFrec.NBufs is the one-based record number of the record currently in the
  399. ; buffer.  Each record is RFrec.BSize large except the _last_ record in the
  400. ; file, which is usually smaller because the file isn't exactly divisible
  401. ; by BSize.
  402. ;
  403. PUBLIC    RFobject@FSeek
  404.     RFsi        equ    (RFrec ptr si)
  405.  
  406. PROC RFobject@FSeek FAR
  407.     BpSp
  408.     push ds            ; save Turbo DS
  409.  
  410.     lds  si, [@self]        ; ds:si points to RFrec
  411.  
  412.     ; make sure BSize > 0 before dividing
  413.     xor  cx, cx
  414.     or   cx, [RFsi.BSize]    ; CX = buffer size.
  415.     jnz  Divide        ; Avoid divide by zero error
  416.     mov  ax, 200        ; return TP divide by zero error code.
  417.     jmp  short DoneFSeek
  418.  
  419.     ; Divide requested file position by BSize to get record number
  420.     ; and offset (modulus).
  421. Divide:    mov  ax, [bp+10]    ; DX:AX = File position requested
  422.     mov  dx, [bp+12]
  423.     div  cx            ; ax = zero based NBufs.
  424.     ; dx = offset into buffer.
  425.     inc  ax            ; Adjust for one-base NBufs
  426.  
  427.     ; BufferNumber is now in AX, Offset in DX
  428.     cmp  [RFsi.NBufs], ax    ; current NBufs = one we're looking for?
  429.     jne  FillerUp        ; no, gotta read it.
  430.     cmp  [RFsi.TotRead], 0    ; yes. Any bytes read into buffer?
  431.     jnz  Filled        ; Yes, we don't need to fill it.
  432.  
  433. FillerUp:            ; Move DOS file pointer to proper record, and fill the buffer
  434.     push dx            ; save requested buffer offset
  435.     dec  ax            ; adjust for zero- base.
  436.     mov  [RFsi.NBufs], ax
  437.     xor  dx, dx        ; prepare to multiply.
  438.     mul  [RFsi.BSize]
  439.  
  440.     mov  bx, [RFsi.Handle]
  441.     mov  cx, ax        ; load CX:DX with record position
  442.     xchg cx, dx
  443.     mov  ax, 4200h        ; DOS move file pointer.
  444.     int  21h
  445.     pop  dx
  446.     jc   DoneFSeek        ; If DOS error, get out.
  447.  
  448.     ; Successful seek.  Now fill the buffer.
  449.     mov  es, [RFsi.BufES]    ; ES = Buffer segment
  450.     mov  bx, si        ; BX = RFrec offset.
  451.     call FillBuf
  452.     mov  si, bx
  453.     jc   DoneFSeek        ; If DOS error, then get out
  454.  
  455. Filled:                ; Buffer is filled.
  456.     ; NBufs is set to proper BufferNumber.
  457.     ; dx = offset in buffer.
  458.  
  459.     ; Adjust RFrec to point to proper position.
  460.     ; set BufCX for next scan.
  461.     mov  ax, [RFsi.TotRead]    ; AX = Total bytes in buffer.
  462.     cmp  ax, dx        ; Is dx within total bytes?
  463.     ja   InBuffer        ; yes, set BufCX
  464.     mov  ax, 100        ; set result to Read Error.
  465.     jmp  short DoneFSeek
  466.  
  467. InBuffer:
  468.     sub  ax, dx
  469.     mov  [RFsi.BufCX], ax    ; set number bytes remaining to scan
  470.  
  471.     ; set BufDI for next scan.
  472.     mov  ax, [RFsi.BufStart] ; AX   = Starting offset of buffer.
  473.     add  ax, dx        ; add offset in buffer to seek to.
  474.     mov  [RFsi.BufDI], ax
  475.     xor  ax, ax        ;  return success.
  476.  
  477. DoneFSeek:
  478.     mov  [RFsi.RFerror], ax
  479.     pop  ds
  480.     SpBp 8
  481. ENDP
  482.  
  483.  
  484. ; FFILEPOS ***************************************************************
  485. ;
  486. ;  FUNCTION FFilePos : LongInt;
  487. ;
  488. ; FFilePos
  489. ; Output
  490. ;    dx:ax = filpos
  491. ;
  492. PUBLIC    RFobject@FFilepos
  493. PROC    RFobject@FFilepos    FAR
  494.     BpSp
  495.     les  di, [@self]        ; load es:bx
  496.     xor  dx, dx
  497.     mov  ax, [RFesdi.NBufs]
  498.     or   ax, ax
  499.     jz   @@Done
  500.     dec  ax
  501.  
  502.     mov  cx, [RFesdi.BSize]
  503.     mul  cx
  504.  
  505.     mov  cx, [RFesdi.BufDI]
  506.     sub  cx, [RFesdi.BufStart]
  507.  
  508.     add  ax, cx
  509.     adc  dx, 0
  510. @@Done:    SpBp 4
  511. ENDP
  512.  
  513. ENDS    CODE
  514. END
  515.